home *** CD-ROM | disk | FTP | other *** search
/ Programmers Heaven 2 / Programmers Heaven 2.iso / files / graphics / library / wgt51_r2.zip / WGT5 / EXAMPLES / WGT55.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-08-03  |  12.9 KB  |  555 lines

  1. /*
  2. ==============================================================================
  3.               WordUp Graphics Toolkit Version 5.0                     
  4.                  Demonstration Program 55                         
  5.                                           
  6.  This program rotates 3 individual objects at the same time and uses Gouraud 
  7.  shading to display them.  It is a more complex version of the first 3D demo 
  8.  since each object has a number of independant variables, and the area each  
  9.  occupies on the screen is dealt with for each object for maximum speed.     
  10.                                           
  11.  *** PROJECT ***                                                             
  12.  This program requires the file WGT5_WC.LIB, and WGT3D_WC.LIB to be linked.  
  13.                                           
  14.  *** DATA FILES ***                                                          
  15.  You must have the MYTRI.3D, MYCUBE.3D, MYCYL.3D, and 3DDEMO.PAL files in    
  16.  your executable dir.                                                        
  17.                                WATCOM C++ VERSION 
  18. ==============================================================================
  19. */
  20. #include <conio.h>
  21. #include <math.h>
  22. #include <stdlib.h>
  23. #include <dos.h>
  24. #include <wgt3d.h>
  25. #include <wgt5.h>
  26.  
  27. /* WGT 3D Object File Format
  28. The following is a description of the file format used in the 3D demos.
  29.  
  30. The first line contains the identification string
  31. "WGT 3D Object File"
  32.  
  33. Then the number of points in the file is on a separate line.
  34. Each point is then stated, with the following format:
  35. x_coord y_coord z_coord sx_value sy_value
  36.  
  37. With hollow and solid polygons, you can use sx as the color of the polygon.
  38. With Gouraud shading, sx is the color at that point.
  39. With Texture mapping, sx,sy is the offset into the texture bitmap.
  40.  
  41. A blank line follows, and then the number of faces is on a new line.
  42. Each face is described as a 4 point sequence, using the points stated above.
  43. Point numbers start at 0.
  44. On the same line, a polygon type number is given.
  45. 0 means hollow
  46. 1 means solid
  47. 2 means lighted Gouraud (brighter closer to you)
  48. 3 means set Gouraud (uses value stored by the vertices above)
  49. 4 means texture mapped (not used in this demo)
  50.  
  51. For example, to make a face with points 0-3, with set Gouraud shading,
  52. the line would be
  53. 0 1 2 3 3
  54.  
  55. Here is an example image with one polygon:
  56.  
  57. WGT 3D Object File
  58. 4
  59. -25 -25 50 140 0
  60. 25 -25 50 195 0
  61. 25 25 50 140 0
  62. -25 25 50 195 0
  63.  
  64. 1
  65. 0 1 2 3 3
  66. */
  67.  
  68. #define HOLLOW 0
  69. #define SOLID 1
  70. #define GOURAUD 2
  71. #define SETGOURAUD 3
  72.  
  73. /* Routines used in this program */
  74. void loadobject(char *,point3d *,short);
  75. void clear_last(void);
  76. void update_screen(void);
  77. void calculate_depth(void);
  78. void sort_polys(void);
  79. void draw_polys(void);
  80. void rotate_objects(void);
  81.  
  82.  
  83. point3d mycube[9];              /* Store data points for each object */
  84. point3d mytri[9];
  85. point3d mycyl[9];
  86.  
  87. point3d finp[90];               /* Stores the final, rotated points */
  88. short numpts[3];                  /* Number of points in each object */
  89. tpolypoint mypoly[4];           /* Used to draw one polygon at a time */
  90.  
  91. short rendermethod;
  92. char c;
  93.  
  94. short sortpoly[100];
  95. short ztotal[100];
  96.  
  97. short maxpoly = 300;
  98. short totalpoly = 0;
  99. short rot;
  100.  
  101. short faces[200][4];
  102. short facetype[200];
  103. short faceowner[200];
  104.  
  105. block other;
  106. color pal[256];
  107. short d, e;
  108.  
  109. typedef struct {         
  110.   short x1;
  111.   short y1;
  112.   short x2;              /* Used to keep track what portion of the */
  113.   short y2;              /* screen has been changed, so we can update */
  114. } rect;                  /* the least amount of video memory */
  115.  
  116.  
  117. typedef struct
  118. {
  119.   rect lastrect, thisrect;
  120.   short addx, addy, addz;
  121.   short curx, cury, curz;
  122. } object3d;
  123.  
  124. object3d myobject[3];
  125.  
  126. short xdir[3] = {1, -1, 1};
  127. short ydir[3] = {1, 1, -1};
  128. short zdir[3] = {-1, 1, 1};
  129. short xpos[3] = {0, 200, -200};
  130. short ypos[3] = {0, 0, 0};
  131. short zpos[3] = {0, 0, 0};
  132.  
  133. int updates, timer;
  134.  
  135. void loadobject (char *fname, point3d *mypoints, short obj)
  136. /* Loads a 3D object file */
  137. {
  138.   short i;
  139.   FILE *objfile;
  140.   char blank[80];
  141.   short addnum = 0;
  142.  
  143.   for (i = 0; i < obj; i++)
  144.     addnum += numpts[i];
  145.  
  146.   objfile = fopen (fname, "rt");
  147.  
  148.   fscanf (objfile,"%s %s %s %s\n", blank, blank, blank, blank);
  149.  
  150.   /* Number of points in this object */
  151.   fscanf (objfile, "%hd\n", &maxpoly);
  152.  
  153.   numpts[obj] = maxpoly;
  154.  
  155.   /* Load the points */
  156.   for (i = 0; i < maxpoly; i++)
  157.     fscanf(objfile, "%hd %hd %hd %hd %hd\n", &mypoints[i].x, &mypoints[i].y,
  158.        &mypoints[i].z, &mypoints[i].sx, &mypoints[i].sy);
  159.  
  160.   /* Number of faces in this object */
  161.   fscanf (objfile, "\n%hd\n", &maxpoly);
  162.   for (i = 0; i < maxpoly; i++)
  163.   {
  164.     for (e = 0; e < 4; e++)
  165.     {
  166.       fscanf (objfile, "%hd ", &faces[i + totalpoly][e]);
  167.       faces[i + totalpoly][e] += addnum;
  168.     }
  169.     fscanf (objfile, "%hd\n", &facetype[i + totalpoly]);
  170.     faceowner[i + totalpoly] = obj;
  171.   }
  172.   totalpoly += maxpoly;
  173.   fclose (objfile);
  174. }
  175.  
  176.  
  177. void clear_last (void)
  178. /* Clears out the last regions of the screen where the objects were */
  179. {
  180.   short i;
  181.   rect *lr;
  182.  
  183.   for (i = 0; i < 3; i++)
  184.   {
  185.     lr = &myobject[i].lastrect;
  186.  
  187.     /* Do clipping for smallest area update */
  188.     if (lr->x1 < 0)
  189.       lr->x1 = 0;
  190.     if (lr->x2 > 319)
  191.       lr->x2 = 319;
  192.     if (lr->y1 < 0)
  193.       lr->y1 = 0;
  194.     if (lr->y2 > 199)
  195.       lr->y2 = 199;
  196.  
  197.     wsetcolor (0);
  198.     /* Change the previous line to the one below in order to see the updating
  199.        rectangular regions */
  200.  
  201.     wbar (lr->x1, lr->y1, lr->x2, lr->y2);
  202.     /* Clear out the area that was drawn in last frame */
  203.   }
  204. }
  205.  
  206.  
  207. void update_screen (void)
  208. /* Copy the regions of the background screen onto the visual screen */
  209. {
  210.   rect *tr;
  211.   rect *lr;
  212.   short i;
  213.  
  214.   for (i = 0; i < 3; i++)
  215.   {
  216.     tr = &myobject[i].thisrect;
  217.     lr = &myobject[i].lastrect;
  218.  
  219.     if (lr->x1 > tr->x1)
  220.       lr->x1 = tr->x1;
  221.     if (lr->x2 < tr->x2)
  222.       lr->x2 = tr->x2;
  223.     if (lr->y1 > tr->y1)
  224.       lr->y1 = tr->y1;
  225.     if (lr->y2 < tr->y2)
  226.       lr->y2 = tr->y2;
  227.     /* See if the previous frame was larger in any direction. If it is, enlarge
  228.        the area so it will copy black over the previous frame. */
  229.  
  230.     /* Do clipping */
  231.     if (lr->x1 < 0)
  232.       lr->x1 = 0;
  233.     if (lr->x2 > 319)
  234.       lr->x2 = 319;
  235.     if (lr->y1 < 0)
  236.       lr->y1 = 0;
  237.     if (lr->y2 > 199)
  238.       lr->y2 = 199;
  239.  
  240.     wcopyscreen (lr->x1, lr->y1, lr->x2, lr->y2, other, lr->x1, lr->y1, NULL);
  241.     /* Copy from our second page to the visual page. */
  242.  
  243.     lr->x1 = tr->x1;
  244.     lr->y1 = tr->y1;
  245.     lr->x2 = tr->x2;
  246.     lr->y2 = tr->y2;
  247.  
  248.     /* Make the last rectangle = current rectangle */
  249.   }
  250. }
  251.  
  252.  
  253. void calculate_depth (void)
  254. /* Prepare the ztotal array for sorting polygons by z value */
  255. {
  256.   short d, e;
  257.  
  258.   for (d = 0; d < maxpoly; d++)
  259.   {
  260.     sortpoly[d] = d;
  261.     ztotal[d] = 0;
  262.     for (e = 0; e < 4; e++)
  263.       ztotal[d] += finp[faces[d][e]].z;
  264.     ztotal[d] /= 4;
  265.   }
  266. }
  267.  
  268.  
  269. void sort_polys (void)
  270. /* Sort those polys using slow bubble sort */
  271. /* There are only about 20 polys max so it probably doesn't matter what
  272.    sorting method you use here. */
  273. {
  274.   short d, e, temp;
  275.  
  276.   for (d = 0; d < maxpoly - 1; d++)
  277.     for (e = d + 1; e < maxpoly; e++)
  278.     {
  279.       if (ztotal[sortpoly[e]] > ztotal[sortpoly[d]])
  280.       {
  281.     temp = sortpoly[e];
  282.     sortpoly[e] = sortpoly[d];
  283.     sortpoly[d] = temp;
  284.       }
  285.     }
  286. }
  287.  
  288.  
  289. void check_rectangle (short obj, short x, short y)
  290. /* Enlarge the update rectangle if needed */
  291. {
  292.   rect *tr;
  293.  
  294.   tr = &myobject[obj].thisrect;
  295.  
  296.   if (x < tr->x1)
  297.     tr->x1 = x;
  298.   if (x > tr->x2)
  299.     tr->x2 = x;
  300.  
  301.   if (y < tr->y1)
  302.     tr->y1 = y;
  303.   if (y > tr->y2)
  304.     tr->y2 = y;
  305.   /* See if the polygon is larger than the current area to update.
  306.      If it is, enlarge the area so all polygons fit inside. */
  307. }
  308.  
  309.  
  310. void draw_polys (void)
  311. /* Draw all of the polygons in order, using our rendering method */
  312. {
  313.   short d, e;
  314.   short cp;
  315.  
  316.   for (d = 0; d < maxpoly; d++)
  317.   {
  318.     cp = sortpoly[d];
  319.     for (e = 0; e < 4; e++)
  320.     {
  321.       mypoly[e].x = finp[faces[cp][e]].x;
  322.       mypoly[e].y = finp[faces[cp][e]].y;
  323.       if (facetype[cp] != GOURAUD)
  324.       {
  325.     /* ARGH! This is very inflexible this way! */
  326.     if (cp < 6)
  327.       mypoly[e].sx = mycube[faces[cp][e]].sx;
  328.     else if (cp < 11)
  329.       mypoly[e].sx = mytri[faces[cp][e] - 8].sx;
  330.     else mypoly[e].sx = mycyl[faces[cp][e] - 13].sx;
  331.       }
  332.     else
  333.       {
  334.     mypoly[e].sx = (255 - finp[faces[cp][e]].z / 7);
  335.     if (mypoly[e].sx < 2) 
  336.       mypoly[e].sx = 2;
  337.     if (mypoly[e].sx > 250) 
  338.       mypoly[e].sx = 250;
  339.       }
  340.       check_rectangle (faceowner[cp], mypoly[e].x, mypoly[e].y);
  341.     }
  342.  
  343.     wsetcolor (mypoly[0].sx);
  344.  
  345.     if (facetype[cp] == HOLLOW)
  346.       whollowpoly (mypoly, 4, 0, 0, CLOSED_POLY);
  347.     else if (facetype[cp] == SOLID)
  348.       wsolidpoly (mypoly, 4, 0, 0, NULL);
  349.     if ((facetype[cp] == GOURAUD) || (facetype[cp] == SETGOURAUD))
  350.       wgouraudpoly (mypoly, 4, 0, 0);
  351.   }
  352. }
  353.  
  354.  
  355. void rotate_objects (void)
  356. /* Make objects spin and rotate all the points */
  357. {
  358.   short i;
  359.  
  360.   for (i = 0; i < 3; i++)
  361.   {
  362.     myobject[i].curx += myobject[i].addx;
  363.     myobject[i].cury += myobject[i].addy;
  364.     myobject[i].curz += myobject[i].addz;
  365.  
  366.     if (myobject[i].curx > 359) 
  367.       myobject[i].curx -= 360;
  368.     if (myobject[i].cury > 359) 
  369.       myobject[i].cury -= 360;
  370.     if (myobject[i].curz > 359) 
  371.       myobject[i].curz -= 360;
  372.     if (myobject[i].curx < 0) 
  373.       myobject[i].curx += 360;
  374.     if (myobject[i].cury < 0) 
  375.       myobject[i].cury += 360;
  376.     if (myobject[i].curz < 0) 
  377.       myobject[i].curz += 360;
  378.  
  379.     wsetrotation (myobject[i].curx, myobject[i].cury, myobject[i].curz);
  380.  
  381.     move_x = xpos[i];
  382.     move_y = ypos[i];
  383.     move_z = zpos[i];
  384.  
  385.     switch (i)
  386.     {
  387.       case 0:  wrotatepoints (mycube, finp, numpts[0]); 
  388.            break;
  389.       case 1:  wrotatepoints (mytri, &finp[numpts[0]], numpts[1]); 
  390.            break;
  391.       case 2:  wrotatepoints (mycyl, &finp[numpts[0]+numpts[1]], numpts[2]);
  392.            break;
  393.     }
  394.   }
  395. }
  396.  
  397.  
  398. void bounce_object (void)
  399. /* Make objects bounce in 3D space.  When they change direction, they also
  400.    change their rotational motion */
  401. {
  402.   short i;
  403.  
  404.   for (i = 0; i < 3; i++)
  405.   {
  406.     xpos[i] += xdir[i] * 4;
  407.     ypos[i] += ydir[i] * 4;
  408.     zpos[i] += zdir[i] * 4;
  409.  
  410.     if (xpos[i] > 400)
  411.     {
  412.       xdir[i] = -1;
  413.       myobject[i].addx = -4;
  414.     }
  415.     if (ypos[i] > 200)
  416.     {
  417.       ydir[i] = -1;
  418.       myobject[i].addy = -4;
  419.     }
  420.     if (zpos[i] > -100)
  421.     {
  422.       zdir[i] = -1;
  423.       myobject[i].addz = -4;
  424.     }
  425.     if (xpos[i] < -400)
  426.     {
  427.       xdir[i] = 1;
  428.       myobject[i].addx = 4;
  429.     }
  430.     if (ypos[i] < -200)
  431.     {
  432.       ydir[i] = 1;
  433.       myobject[i].addy = 4;
  434.     }
  435.     if (zpos[i] < -1900)
  436.     {
  437.       zdir[i] = 1;
  438.       myobject[i].addz = 4;
  439.     }
  440.   }
  441. }
  442.  
  443.  
  444. void invert_rectangles (void)
  445. {
  446.   short i;
  447.  
  448.   for (i = 0; i < 3; i++)
  449.   {
  450.     myobject[i].thisrect.x1 = 319;
  451.     myobject[i].thisrect.y1 = 199;
  452.     myobject[i].thisrect.x2 = 0;
  453.     myobject[i].thisrect.y2 = 0;
  454.   }
  455. }
  456.  
  457.  
  458. void timerctr (void)
  459. {
  460.   timer++;  
  461. }
  462.  
  463.  
  464. void main (void)
  465. {
  466.   short i;
  467.   short oldmode;
  468.  
  469.   oldmode = wgetmode ();
  470.   
  471.   if ( !vgadetected () )
  472.   {
  473.     printf ("Error - VGA card required for any WGT program.\n");
  474.     exit (0);
  475.   }
  476.   printf ("WGT Example #55\n\n");
  477.   
  478.   printf ("3d Object Demo #2\n\n");
  479.   printf ("Choose your rendering type:\n");
  480.   printf ("0: Wireframe\n");
  481.   printf ("1: Solid\n");
  482.   printf ("2: Gouraud\n");
  483.   printf ("3: Set Gouraud\n");
  484.  
  485.   scanf ("%i", &rendermethod);
  486.  
  487.   vga256 ();
  488.  
  489.   winit3d ();
  490.   winitpoly (WGT_SYS.yres);
  491.  
  492.   other = wnewblock (0, 0, 319, 199);
  493.   wloadpalette ("3ddemo.pal", pal);
  494.  
  495.   if (rendermethod == GOURAUD)   /* Lighted Gouraud, so create a palette with
  496.                     gradually changing colors. */
  497.   {
  498.    for (i = 0; i < 64; i++)
  499.      wsetrgb (i, 0, 0, i, pal);
  500.    for (i = 64; i < 256; i++)
  501.      wsetrgb (i, (i - 64) / 2, (i - 64) / 2, 64, pal);
  502.   }
  503.  
  504.   wsetpalette(0, 255, pal);
  505.  
  506.   maxpoly = 0;
  507.   loadobject ("mycube.3d", mycube, 0);
  508.   loadobject ("mytri.3d", mytri, 1);
  509.   loadobject ("mycyl.3d", mycyl, 2);
  510.  
  511.   for (i = 0; i < totalpoly; i++)
  512.     facetype[i] = rendermethod;
  513.  
  514.   for (i = 0; i < 3; i++)
  515.   {
  516.     xpos[i] = ((rand () % 400) - 200);
  517.     ypos[i] = ((rand () % 200) - 100);
  518.     zpos[i] = -((rand () % 1800) + 100);
  519.   }
  520.  
  521.   wsetscreen (other);
  522.  
  523.   maxpoly = totalpoly;
  524.  
  525.   /* Main loop */
  526.   timer = 0;
  527.   winittimer ();
  528.   wstarttimer (timerctr, TICKS(100));
  529.   do {
  530.     invert_rectangles ();
  531.  
  532.     clear_last ();
  533.  
  534.     bounce_object ();
  535.     rotate_objects ();
  536.     calculate_depth ();
  537.     sort_polys ();
  538.     draw_polys ();
  539.     update_screen ();
  540.     updates++;
  541.   } while (!kbhit ());
  542.   wstoptimer ();
  543.   wdonetimer ();
  544.   // get final time
  545.   
  546.   wdeinitpoly ();
  547.   wsetmode (oldmode);
  548.   
  549.   printf ("\nElapsed time (hundredths of seconds): %i", timer);
  550.   printf ("\n# updates: %d", updates);
  551.   printf ("\nAverage frame rate: %2.2f frames/sec\n", (float)updates / (float)(timer / 100));
  552. }
  553.  
  554.  
  555.